--[[
 -- *名称:FourTake3SingleTypeAnalyzer
 -- *描述:四带二牌型分析器
 -- *版权:Copyright © 2016-2018 深圳市三只小熊科技有限公司 版权所有
 -- *作者:Administrator
 -- *创建日期:2017-11-09
 -- *修改日期:2017-11-09
 ]]
local PdkSuitAnalyzer = require(basePath.."suit/ddzsuitanalyzer");
local BombTypeAnalyzer =  require(basePath.."suit/bomb/bombtypeanalyzer");
local Cards = require(basePath .. "domain/cards");
local FourTake3SingleTypeAnalyzer = pokercore.class(PdkSuitAnalyzer,false);
local TUPLE_SIZE = 7;
local FourTakeSingleAnalyzer = require(basePath .. "suit/fourtakesingle/fourtakesingletypeanalyzer") ;
local fourTakeSingleTypeAnalyzer = pokercore.new(FourTakeSingleAnalyzer);

function FourTake3SingleTypeAnalyzer:getSuitType()
	-- dump(DdzCardTypes.FOUR_TAKE_3_SINGLE, "DdzCardTypes.FOUR_TAKE_3_SINGLE-->");
	return DdzCardTypes.FOUR_TAKE_3_SINGLE;
end

function FourTake3SingleTypeAnalyzer:doCheckRule( cards, term, result )
	if result:getCardNum() ~= TUPLE_SIZE then -- 八张牌，考虑 44443355 55556666
		return false;
	end
	if result:isAllCardLazi() then  -- 全是癞子
		return false;
	end
	local allValues = result:getNoneLaziValueCounter():getAllValues(); -- 非癞子的点数
	local allValueSize = #allValues;
	if allValueSize > 4 then -- 四带3牌型最多只有4种点数 ****123
		return false;	
	end
	local laiziCardNum = result:getLaziCardNum();
	for i,value in ipairs(allValues) do
		local valueNum = result:getNoneLaziValueCounter():getValueCount(value);
		if (valueNum + laiziCardNum >= BombTypeAnalyzer.TUPLE_SIZE) then
			return true;
		end
	end
	return false;
end

function FourTake3SingleTypeAnalyzer:doAnalysizeLaizi( cards, term, onlyMaxValue )
	local cardsResult = {};
	local result = cards:getResult();
	local laiziCardNum = result:getLaziCardNum();
	-- 只有2种或3种点数的情况
	if laiziCardNum >= 4 then -- // 4个癞子任意组成 4带3
		self:makeItInAllValues(cards, term, onlyMaxValue, cardsResult);
	else -- // 3个癞子 有限情况下组成4带3
		self:makeItInSomeValues(cards, term, onlyMaxValue, cardsResult);
	end
	return cardsResult;
end
---
 -- 在已知值中寻找四带两对
 -- @DateTime 2017-11-09
 -- @param    cards [description]
 -- @param    term [description]
 -- @param    onlyMaxValue [description]
 -- @param    cardsResult [description]
 -- @return    [description]
 --
function FourTake3SingleTypeAnalyzer:makeItInSomeValues( cards, term, onlyMaxValue, cardsResult )
	local result = cards:getResult();
	local laiziCardList = cards:subList(result:getCardNum() - result:getLaziCardNum()+1, result:getCardNum());
	local allValues = result:getNoneLaziValueCounter():getAllValues();
	local laiziCardNum = result:getLaziCardNum();
	for i = #allValues, 1, -1 do 
		local i_valueTemp = allValues[i];
		result:setSortFirstValue(i_valueTemp);
		local i_valueTempNum = result:getNoneLaziValueCounter():getValueCount(i_valueTemp);
		local i_needLaiziNum = 4 - i_valueTempNum;
		if i_needLaiziNum <= laiziCardNum then 
			local laiziCardIndex = 0;
			for i_laiziIndex = 1, i_needLaiziNum do
				laiziCardIndex = laiziCardIndex + 1; 
				laiziCardList[laiziCardIndex]:changeCard(i_valueTemp);
			end
			--如果有剩下补齐成对儿
			for j = laiziCardIndex+1, laiziCardNum do 
				laiziCardList[j]:changeCard(laiziCardList[laiziCardIndex+1]:getNumber());
			end
			if i_needLaiziNum <= laiziCardNum then 
				local cardsCopy = cards:clone();	
				self:analysize(cardsCopy,term);
				table.insert(cardsResult,cardsCopy:clone());
				if onlyMaxValue then 
					break;
				end
			end
		end
	end
end
---
 -- 遍历所有值寻找四带两对
 -- @DateTime 2017-11-09
 -- @param    cards [description]
 -- @param    term [description]
 -- @param    onlyMaxValue [description]
 -- @param    cardsResult [description]
 -- @return    [description]
 --
function FourTake3SingleTypeAnalyzer:makeItInAllValues( cards, term, onlyMaxValue, cardsResult )
	local result = cards:getResult();
	--print("FourTake3SingleTypeAnalyzer:makeItInAllValues cards",cards);
	local laiziCardList = cards:subList(result:getCardNum() - result:getLaziCardNum()+1, result:getCardNum());
	local allValues = result:getNoneLaziValueCounter():getAllValues(); -- 非癞子的点数
	local laiziCardNum = result:getLaziCardNum();
	for valueTemp = PokerGameConstant.NUMBER_2_VALUE, PokerGameConstant.NUMBER_3_VALUE, -1 do 
		result:setSortFirstValue(valueTemp);
		local valueTempNum = result:getNoneLaziValueCounter():getValueCount(valueTemp);
		local laiziCardIndex = 0;
		local needLaiziNum = 4 - valueTempNum;
		--print("####### needLaiziNum->",needLaiziNum);
		--print("####### laiziCardList->",#laiziCardList);
		for i = 1, needLaiziNum do 
			laiziCardIndex = laiziCardIndex + 1;
			laiziCardList[laiziCardIndex]:changeCard(valueTemp);
		end
		-- 如果有剩下补齐成对儿
		for j = laiziCardIndex+1, laiziCardNum do 
			laiziCardList[j]:changeCard(laiziCardList[laiziCardIndex+1]:getNumber());
		end
		local cardsCopy = cards:clone();	
		self:analysize(cardsCopy,term);
		table.insert(cardsResult,cardsCopy:clone());
		if onlyMaxValue then 
			break; -- 取完最大一组就跳出
		end
	end
end


--提牌算法


--@Override
function FourTake3SingleTypeAnalyzer:containsPossibleCards( handCards,  term) 
	local result = handCards:getResult();
	if (result:getCardNum() < TUPLE_SIZE) then
		return false;
	end
	local allValues = result:getNoneLaziValueCounter():getAllValues(); -- // 非癞子的点数
	local laiziCardNum = result:getLaziCardNum();
	for i,value in ipairs(allValues) do
		local valueNum = result:getNoneLaziValueCounter():getValueCount(value);
		if (valueNum + laiziCardNum >= 4) then
			return true;
		end

	end
	return  false;
end

--/** 最多使用癞子的数量 */
local  MAX_USE_LAIZI_CARD_NUM = 7;

--/** 防重复判定的比例值 参照 int key = count_3_value * TUPLE_WEIGHT + count_1_value_a + count_1_value_b; */
local TUPLE_WEIGHT = 1000000;

--/** 癞子权重，区分癞子变成的5 和 原本就是5 */
local LAIZI_WEIGHT = 1000;
	
--@Override
function FourTake3SingleTypeAnalyzer:doListPossibleCards(handCards, term) 
	local cardsResult = {} ;
	--// 非癞子部分
	local result = handCards:getResult();
	local noneLaiziCardList = handCards:subList(1, result:getNoneCardNum());
	local noneLaiziCards = DdzTypeUtil.createCardsCopy(noneLaiziCardList);
	noneLaiziCards:setResult(handCards:getResult():clone());
	local noneLaiziCardsResult = noneLaiziCards:getResult();
	noneLaiziCardsResult:collectNumber(noneLaiziCards, term);
	--// 癞子部分
	local laiziCardList = handCards:subList(result:getNoneCardNum()+1, result:getCardNum());
	local laiziCards = DdzTypeUtil.createCardsCopy(laiziCardList);
	laiziCards:setResult(handCards:getResult():clone());
	local laiziCardsResult = laiziCards:getResult();
	laiziCardsResult:collectNumber(laiziCards, term);
	
	local maxLoseValue = 0; --// 寻找最大遗失的牌 让***5可以出现，但是仅一次
	for valueTemp = PokerGameConstant.NUMBER_2_VALUE --// 从小开始
			,PokerGameConstant.NUMBER_3_VALUE, -1 do
		if (result:getNoneLaziValueCounter():getValueCount(valueTemp) == 0) then
			maxLoseValue = valueTemp;
			break;
		end
	end
	local laiziCardNum = result:getLaziCardNum();
	local maxUseLaiziCardNum = MAX_USE_LAIZI_CARD_NUM < laiziCardNum and MAX_USE_LAIZI_CARD_NUM or laiziCardNum;
	local exsitKeys = {}; -- // 记录已经组成三带一的value
	--print("FourTake3SingleTypeAnalyzer:doListPossibleCards maxUseLaiziCardNum->",maxUseLaiziCardNum);
	for useLaiziCardNum = 0,maxUseLaiziCardNum do
		if (useLaiziCardNum < MAX_USE_LAIZI_CARD_NUM) then --// 用了 0.1.2.3 个癞子
			for valueTemp = PokerGameConstant.NUMBER_3_VALUE  --// 从小开始
					,PokerGameConstant.NUMBER_2_VALUE do
				local modelCardsCopy = noneLaiziCards:clone(); -- // 常规牌副本
				local modelResultCopy = modelCardsCopy:getResult();
				local useLaiziCardList = DdzTypeUtil.cloneSublistedCards(laiziCards, 1, useLaiziCardNum); --// 补癞子
				local valueTempNum = modelResultCopy:getNoneLaziValueCounter():getValueCount(valueTemp);
				local needLaiziCardNum = BombTypeAnalyzer.TUPLE_SIZE - valueTempNum;
				needLaiziCardNum = needLaiziCardNum > 0 and needLaiziCardNum or 0;
				if (needLaiziCardNum == 0) then
					local removedCardList = DdzTypeUtil.cloneRemovedCards(modelCardsCopy, valueTemp, BombTypeAnalyzer.TUPLE_SIZE);
					local tupleCards = pokercore.new(Cards,removedCardList);
					local remainCards = DdzTypeUtil.cloneCardsAndAddCardList(modelCardsCopy, useLaiziCardList);
					local takenCardsList = fourTakeSingleTypeAnalyzer:repeatSelectSingleCards(remainCards, 3, term);
					for _,takenCards in ipairs(takenCardsList) do
						----dump(tupleCards,"合并之前")
						local resultCards = DdzTypeUtil.cloneCardsAndAddCards(tupleCards, takenCards);
						----dump(resultCards,"合并之后")
						local key = valueTemp * TUPLE_WEIGHT;
						for _,card in ipairs(takenCards.cardList) do
							key = key + card:getValue();
							if card:isLazi() then -- // 癞子权重，区分癞子变成的5 和 原本就是5
								key = key + card:getValue() * LAIZI_WEIGHT;
							end
						end
						if not exsitKeys[key] and self:match(resultCards, term) then
							exsitKeys[key] = true;
							--// 保证排序
							resultCards:getResult():setSortFirstValue(valueTemp);
							self:analysize(resultCards, term);
							table.insert(cardsResult,resultCards);
						end
					end
				else -- // 需要癞子来拼凑
					if (needLaiziCardNum == BombTypeAnalyzer.TUPLE_SIZE 
							and valueTemp ~= maxLoseValue) then
						--// 这里是对癞子做tuple的去重
						--// 否则会出现 ****带89 既能是 3333带89 也能是 4444带89 5555带89
						--continue;
					
					elseif (useLaiziCardNum >= needLaiziCardNum) then -- // 癞子足够拼凑
						local removedCardList = DdzTypeUtil.cloneRemovedCards(modelCardsCopy, valueTemp, valueTempNum);
						for i = 1, needLaiziCardNum  do
							local laiziCard =  table.remove(useLaiziCardList,1);
							laiziCard:changeCard(valueTemp);
							table.insert(removedCardList,laiziCard);
						end
						for _,laiziCard in ipairs(useLaiziCardList) do
							laiziCard:changeCard(laiziCard:getValue());
						end
						local tupleCards = pokercore.new(Cards,removedCardList);
						local remainCards = DdzTypeUtil.cloneCardsAndAddCardList(modelCardsCopy, useLaiziCardList);
						local takenCardsList = fourTakeSingleTypeAnalyzer:repeatSelectSingleCards(remainCards, 3, term);
						for _, takenCards in ipairs(takenCardsList) do
							local resultCards = DdzTypeUtil.cloneCardsAndAddCards(tupleCards, takenCards);
							local key = valueTemp * TUPLE_WEIGHT;
							for _,card in ipairs(takenCards.cardList) do
								key = key + card:getValue();
								if card:isLazi() then -- // 癞子权重，区分癞子变成的5 和 原本就是5
									key = key + card:getValue() * LAIZI_WEIGHT;
								end
							end
							if not exsitKeys[key] and self:match(resultCards, term) then
								exsitKeys[key] = true;
								--// 保证排序
								resultCards:getResult():setSortFirstValue(valueTemp);
								self:analysize(resultCards, term);
								table.insert(cardsResult,resultCards);
							end
						end
					end
				end
			end
		else  -- // 用了 4个癞子
			for valueTemp = PokerGameConstant.NUMBER_3_VALUE --// 从小开始
					, PokerGameConstant.NUMBER_2_VALUE do
				local modelCardsCopy = laiziCards:clone();  --// 常规牌补上癞子
				local modelResultCopy =  modelCardsCopy:getResult();
				if (modelResultCopy:getAllValueCounter():getValueCount(valueTemp) >= BombTypeAnalyzer.TUPLE_SIZE) then
					local removedCardList = DdzTypeUtil.cloneRemovedCards(modelCardsCopy, valueTemp, BombTypeAnalyzer.TUPLE_SIZE);
					local tupleCards = new(Cards,removedCardList);
					local takenCardsList = fourTakeSingleTypeAnalyzer:repeatSelectSingleCards(modelCardsCopy, 3, term);
					for _,takenCards in ipairs(takenCardsList) do
						local resultCards = DdzTypeUtil.cloneCardsAndAddCards(tupleCards, takenCards);
						for _,card in ipairs(resultCards.cardList) do
							if card:hasNotChanged() then -- // 有的经过处理已经被赋值了不能再改变
								card:changeCard(card:getValue());
							end
						end
						if (self:match(resultCards, term)) then
							--// 保证排序
							resultCards:getResult():setSortFirstValue(valueTemp);
							self:analysize(resultCards, term);
							table.insert(cardsResult,resultCards);
						end
					end
				end
			end
		end
	end
	return cardsResult;
end

return FourTake3SingleTypeAnalyzer;

